<?php
namespace brenda_template{
	
	class Tokenizer extends Lexical_Component{
		
		private $_tokens_info = null;
		
		private $_blocks_info = null;
		
		private $_outside_block = null;
		
		private $error = null;
		
		function init($bt_document){
			
			$state = false;
			
			$this->_blocks_info = null;
			
			$this->_tokens_info = null;
			
			$this->_outside_block = null;
			
			$this->error = null;
			
			$bt_document_readable = $this->read_document($bt_document);
			
			$all_blocks = $this->find_blocks($bt_document_readable);
			
			if( count($all_blocks) > 0){
				
				$state = true;
				
				$this->_blocks_info = $all_blocks;
				 
				foreach($all_blocks as $block){
				
					$this->_tokens_info[] = $this->find_tokens($block);
				}
			}
			
			return $state;
		}
		
		private function find_tokens($bt_block){
			
			$bt_tokens = $this->_lexical_components;
			
			$bt_tokens_omited = $this->_lexical_component_omited;
			
			$token_founded = null;
			
			$posible_tokens = 0;
			
			$character_position =  $posible_tokens_past = 0;
			
			$character_incrementer = 1;
			
			$token = null;
			
			$token_past = null;
			
			$block_line= $bt_block["open_line"];
			
			$line = null;
			
			for( $i = 0; $i <= strlen($bt_block["content"]); $i++ ){
				
				$token_subject = substr($bt_block["content"],$character_position,$character_incrementer);
				
				$new_line = substr($bt_block["content"],$i,1);
				
				$posible_tokens_past = $posible_tokens;
				
				$posible_tokens = 0;
				
				$token_past = $token;
				
				foreach ($bt_tokens as $key => $value){
					if(preg_match($value["pattern"], $token_subject)){
						$posible_tokens++;
						$token = array(
							"line"=>count($line) + $block_line,
							"token"=>$key,
							"lexema"=>$token_subject,
							"position_init"=>$character_position,
							"position_end"=>$character_position+$character_incrementer,
							"lenght"=>$character_incrementer,
						);
						
					}
				}
				
				preg_match('/^\n$/D', $new_line) ? $line[$i]= null:"";
				
				$character_incrementer++;
				
				if($posible_tokens == 0 && $posible_tokens_past == 1){
					
					$posible_tokens_past = 0;
					
					$character_incrementer = 1;
					
					$new_token = $this->save_token($token_past);
					 
					$new_token ? $token_founded[] = $new_token : "" ;
					
					$token = $token_past = null;
					
					$i > 1 ? --$i : $i ;
					
					$character_position = $i;
				}
			}
			
			
			if($posible_tokens == 1 ){
					
				$new_token = $this->save_token($token);
					 
				$new_token ? $token_founded[] = $new_token : "" ;
			}
			
			if( ($i - 2) != $character_position ){
				
				//echo "error\n";
			} 
			
			return $token_founded;
		}
		
		private function save_token($token_past){
			
			$new_token = null;
			
			if(!$this->is_token_omited($token_past)){
			
				$keyword = $this->is_keyword($token_past);
			
				if($keyword !== false){
						
					$token_past["token"] = $this->_keywords[$keyword];
				}
			
				$new_token = $token_past ;
			}
			return $new_token;
		}
		private function is_token_omited($token){
			
			return in_array($token["token"],$this->_lexical_component_omited);
		}
		
		private function is_keyword($token){
			
			return array_search($token["lexema"], $this->_keywords);
		}
		private function find_blocks($bt_document){
			
			$bt_open_state = false;
			
			$token = null;
			
			$line_count = 1;
			
			$block_count = 0;
			
			$block_info = null;
			
			for( $i = 0; $i < strlen($bt_document); $i++ ){
				
				if(substr($bt_document, $i, 1) !== "\n"){
					
					switch ($bt_open_state){
						case false:
							$token = substr($bt_document, $i, strlen($this->_open_bt["literal"]));
							
							if($token == $this->_open_bt["literal"]){
								
								$bt_open_state = true;
								
								$open_line =$line_count;
								
								$open_character_position = ($i + strlen($this->_open_bt["literal"]));
							}
							break;
						case true:
							$token = substr($bt_document, $i, strlen($this->_close_bt["literal"]));
								
							if($token == $this->_close_bt["literal"]){
								
								$bt_open_state = false;
								
								$block_info[$block_count++] = array(
									"open_line"=>$open_line,
									"open_character_position"=>$open_character_position,
									"close_line"=>$line_count,
									"close_character_position"=>($i),
									"content"=>
										substr(
											$bt_document,
											$open_character_position,
											( $i - $open_character_position)
										)
								);
								
								unset($open_line);
								
								unset($open_character_position);
							}
							break;
					}
					
				}
				else{
					$line_count++;
				}
			}
			
			$bt_open_state == true ? $block_info = null : "";
			
			return $block_info;
		}
		
		private function read_document($bt_document){
			
			$document = is_string($bt_document) ? $bt_document : "";
			 
			if(file_exists($bt_document) && is_readable($bt_document)){
				
				$document = file_get_contents($bt_document);
			}
			
			return $document;
		}
		
		public function get_blocks_info(){
			
			return $this->_blocks_info;
		}
		
		public function get_tokens_info(){
			
			return $this->_tokens_info;
		}
		
		function lasted_error(){
			
			return $this->error;
		}
	}
}
?>